package com.ddwl.shop.repository.impl;

import com.ddwl.common.constant.ShopEnum;
import com.ddwl.schema.bo.shop.QueryNearShopBo;
import com.ddwl.shop.dao.model.ShopLoc;
import com.ddwl.shop.repository.ShopLocRepositoryAdvance;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * @author Fu Zhaohui
 * @version 1.0.0.RELEASE
 * @date 2020/3/6 2:20 下午
 */
@RequiredArgsConstructor
public class ShopLocRepositoryImpl implements ShopLocRepositoryAdvance {

    private final MongoTemplate template;

    @Override
    public List<ShopLoc> near(QueryNearShopBo bo, Integer page, Integer size) {
        Point point = new Point(bo.getLng(), bo.getLat());
        Criteria criteria = Criteria.where("type").in(0, 2).and("status").is(ShopEnum.ShopStatus.NORMAL.getCode());
        if (StringUtils.hasText(bo.getKeyword())) {
            criteria.and("name").regex(bo.getKeyword(), "m");
        }
        NearQuery near = NearQuery.near(point, Metrics.KILOMETERS).spherical(true).query(Query.query(criteria)).with(PageRequest.of(page - 1, size));
        if (bo.getLongDistance() != null) {
            near.maxDistance(bo.getLongDistance(), Metrics.KILOMETERS);
        }
        AggregationResults<ShopLoc> aggregationResults = template.aggregate(Aggregation.newAggregation(
                ShopLoc.class,
                Aggregation.geoNear(near, "distance"),
                Aggregation.sort(Sort.Direction.ASC, "distance")),
                ShopLoc.class, ShopLoc.class);
        return aggregationResults.getMappedResults();
    }
}
